"""
评价对话框
用于用户撰写和提交评价
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from core.models.review import Review
from core.utils.logger import debug, info, warning, error
from core.utils.image_utils import copy_review_image, validate_image_file, load_thumbnail
from ui.styles.theme import Theme
import os


class ReviewDialog:
    """评价对话框"""
    
    def __init__(self, parent, controller, product, order):
        """
        初始化评价对话框
        
        Args:
            parent: 父窗口
            controller: 主控制器
            product: 商品对象
            order: 订单对象
        """
        self.parent = parent
        self.controller = controller
        self.product = product
        self.order = order
        self.review_service = controller.review_service
        self.user = controller.auth_service.current_user
        
        self.rating = 0
        self.images = []  # 存储原始上传路径
        self.saved_images = []  # 存储复制后的路径
        
        self._create_dialog()
    
    def _create_dialog(self):
        """创建对话框"""
        self.dialog = tk.Toplevel(self.parent)
        self.dialog.title(f"撰写评价 - {self.product.name}")
        self.dialog.geometry('550x1000')
        self.dialog.resizable(True, True)
        self.dialog.minsize(500, 600)
        self.dialog.transient(self.parent)
        self.dialog.grab_set()
        
        # 设置窗口居中
        self.dialog.update_idletasks()
        x = (self.dialog.winfo_screenwidth() // 2) - (550 // 2)
        y = (self.dialog.winfo_screenheight() // 2) - (700 // 2)
        self.dialog.geometry(f'550x700+{x}+{y}')
        
        # 创建滚动框架
        canvas = tk.Canvas(self.dialog)
        scrollbar = ttk.Scrollbar(self.dialog, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)
        
        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )
        
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)
        
        # 主框架
        main_frame = ttk.Frame(scrollable_frame, padding=20)
        main_frame.pack(fill='both', expand=True)
        
        # 布局滚动组件
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 绑定鼠标滚轮事件
        def _on_mousewheel(event):
            canvas.yview_scroll(int(-1*(event.delta/120)), "units")
        
        canvas.bind_all("<MouseWheel>", _on_mousewheel)
        
        # 当对话框关闭时解绑鼠标滚轮事件
        def _on_close():
            canvas.unbind_all("<MouseWheel>")
            self.dialog.destroy()
        
        self.dialog.protocol("WM_DELETE_WINDOW", _on_close)
        
        # 标题
        title_label = ttk.Label(main_frame, text='📝 撰写评价', font=('Arial', 16, 'bold'))
        title_label.pack(pady=(0, 20))
        
        # 商品信息
        product_frame = ttk.LabelFrame(main_frame, text='商品信息', padding=10)
        product_frame.pack(fill='x', pady=(0, 20))
        
        ttk.Label(product_frame, text=f'商品：{self.product.name}', font=('Arial', 12)).pack(anchor='w')
        ttk.Label(product_frame, text=f'价格：¥{self.product.price:.2f}', font=('Arial', 10), foreground='#666').pack(anchor='w')
        
        # 评分区域
        rating_frame = ttk.LabelFrame(main_frame, text='您的评分', padding=10)
        rating_frame.pack(fill='x', pady=(0, 20))
        
        # 星级选择器
        from ui.components.star_rating import StarRating
        self.star_rating = StarRating(
            rating_frame, 
            rating=0, 
            editable=True, 
            on_change=self._on_rating_change,
            size=20
        )
        self.star_rating.pack(anchor='w')
        
        # 评分文字
        self.rating_text_label = ttk.Label(rating_frame, text='请选择评分', font=('Arial', 10), foreground='#666')
        self.rating_text_label.pack(anchor='w', pady=(5, 0))
        
        # 评论区域
        comment_frame = ttk.LabelFrame(main_frame, text='评价内容', padding=10)
        comment_frame.pack(fill='x', pady=(0, 20))
        
        ttk.Label(comment_frame, text='请分享您的使用体验（可选）：', font=('Arial', 10)).pack(anchor='w')
        
        # 评论文本框
        self.comment_text = tk.Text(comment_frame, height=4, wrap='word', font=('Arial', 10))
        self.comment_text.pack(fill='x', pady=(5, 0))
        
        # 图片上传区域
        image_frame = ttk.LabelFrame(main_frame, text='上传图片（可选）', padding=10)
        image_frame.pack(fill='x', pady=(0, 20))
        
        # 图片上传按钮
        upload_btn = ttk.Button(image_frame, text='📷 选择图片', command=self._upload_images)
        upload_btn.pack(anchor='w')
        
        # 图片预览区域
        self.image_preview_frame = ttk.Frame(image_frame)
        self.image_preview_frame.pack(fill='x', pady=(10, 0))
        
        # 按钮区域 - 固定在底部
        button_frame = ttk.Frame(scrollable_frame)
        button_frame.pack(fill='x', pady=(20, 0), padx=20)
        
        # 添加分隔线
        separator = ttk.Separator(button_frame, orient='horizontal')
        separator.pack(fill='x', pady=(0, 15))
        
        # 按钮容器
        btn_container = ttk.Frame(button_frame)
        btn_container.pack(fill='x')
        
        # 提交评价按钮 - 更突出的样式（放在左边）
        submit_btn = ttk.Button(btn_container, text='📝 提交评价', command=self._submit, 
                               style='Accent.TButton', width=18)
        submit_btn.pack(side='left')
        
        # 取消按钮（放在右边，与提交按钮有间距）
        cancel_btn = ttk.Button(btn_container, text='取消', command=self._cancel, width=15)
        cancel_btn.pack(side='left', padx=(15, 0))
        
        # 添加提示文字
        tip_label = ttk.Label(button_frame, text='💡 请先选择评分，然后撰写您的评价内容', 
                             font=('Arial', 9), foreground='#666')
        tip_label.pack(pady=(10, 0))
    
    def _on_rating_change(self, rating):
        """评分变化回调"""
        self.rating = rating
        rating_texts = {
            1: "很差",
            2: "较差", 
            3: "一般",
            4: "较好",
            5: "很好"
        }
        text = rating_texts.get(rating, "未知")
        self.rating_text_label.config(text=f'{rating}星 - {text}')
    
    def _upload_images(self):
        """上传图片"""
        try:
            filetypes = [
                ('图片文件', '*.jpg *.jpeg *.png *.gif *.bmp'),
                ('JPEG', '*.jpg *.jpeg'),
                ('PNG', '*.png'),
                ('所有文件', '*.*')
            ]
            
            files = filedialog.askopenfilenames(
                title='选择图片',
                filetypes=filetypes
            )
            
            if files:
                # 限制最多6张图片
                if len(self.images) + len(files) > 6:
                    messagebox.showwarning('图片数量限制', '最多只能上传6张图片')
                    return
                
                # 验证并处理每个文件
                for file_path in files:
                    # 验证图片
                    is_valid, error_msg = validate_image_file(file_path, max_size_mb=5)
                    if not is_valid:
                        messagebox.showwarning('图片验证失败', error_msg)
                        continue
                    
                    # 复制图片到review_images目录
                    try:
                        saved_path = copy_review_image(file_path)
                        self.images.append(file_path)  # 保留原始路径用于显示
                        self.saved_images.append(saved_path)  # 保存复制后的路径
                        info(f"图片已保存: {saved_path}")
                    except Exception as e:
                        error(f"保存图片失败: {e}")
                        messagebox.showerror('保存失败', f'保存图片时发生错误: {e}')
                        # 如果保存失败，清理已添加的记录
                        if file_path in self.images:
                            self.images.remove(file_path)
                        continue
                
                # 更新预览
                if self.images:
                    self._update_image_preview()
                    messagebox.showinfo('上传成功', f'已成功上传 {len(self.images)} 张图片')
                
        except Exception as e:
            error(f"上传图片失败: {e}")
            messagebox.showerror('上传失败', f'上传图片时发生错误: {e}')
    
    def _update_image_preview(self):
        """更新图片预览（带缩略图）"""
        # 清除现有预览
        for widget in self.image_preview_frame.winfo_children():
            widget.destroy()
        
        if not self.images:
            return
        
        # 显示图片预览
        ttk.Label(self.image_preview_frame, text=f'已选择 {len(self.images)} 张图片：', font=('Arial', 9)).pack(anchor='w')
        
        # 创建图片预览网格
        preview_frame = ttk.Frame(self.image_preview_frame)
        preview_frame.pack(fill='x', pady=(5, 0))
        
        # 每行显示3张图片
        cols_per_row = 3
        for i in range(len(self.images)):
            row = i // cols_per_row
            col = i % cols_per_row
            
            # 创建单个图片的预览框架
            item_frame = ttk.Frame(preview_frame)
            item_frame.grid(row=row, column=col, padx=5, pady=5, sticky='nw')
            
            # 获取主题颜色
            border_color = Theme.get_color('border')
            bg_color = Theme.get_color('bg_tertiary')
            fg_color = Theme.get_color('fg_primary')
            
            # 加载缩略图
            thumbnail = load_thumbnail(self.images[i], size=(80, 80))
            if thumbnail:
                # 创建Canvas用于显示缩略图
                canvas = tk.Canvas(item_frame, width=80, height=80, highlightthickness=1, highlightbackground=border_color, bg=bg_color)
                canvas.pack()
                canvas.create_image(40, 40, image=thumbnail)
                # 保存引用避免被GC
                canvas.image = thumbnail
            else:
                # 如果加载失败，显示占位符
                canvas = tk.Canvas(item_frame, width=80, height=80, highlightthickness=1, highlightbackground=border_color, bg=bg_color)
                canvas.pack()
                canvas.create_text(40, 40, text='❌', font=('Arial', 24), fill=fg_color)
            
            # 显示文件名
            filename = os.path.basename(self.images[i])
            if len(filename) > 12:
                filename = filename[:9] + '...'
            
            filename_label = ttk.Label(item_frame, text=filename, font=('Arial', 8))
            filename_label.pack(pady=(2, 0))
            
            # 删除按钮
            delete_btn = ttk.Button(item_frame, text='🗑️', width=5, 
                                  command=lambda idx=i: self._remove_image(idx))
            delete_btn.pack(pady=(2, 0))
    
    def _remove_image(self, index):
        """删除图片"""
        if 0 <= index < len(self.images):
            # 删除保存的文件
            if index < len(self.saved_images):
                saved_path = self.saved_images[index]
                try:
                    if os.path.exists(saved_path):
                        os.remove(saved_path)
                except Exception as e:
                    error(f"删除图片文件失败: {e}")
            
            # 从列表中移除
            self.images.pop(index)
            if index < len(self.saved_images):
                self.saved_images.pop(index)
            self._update_image_preview()
    
    def _submit(self):
        """提交评价"""
        try:
            # 验证评分
            if self.rating == 0:
                messagebox.showwarning('评分必填', '请先选择评分（1-5星）')
                return
            
            # 获取评论内容
            comment = self.comment_text.get('1.0', tk.END).strip()
            
            # 显示提交中的提示
            self.dialog.config(cursor='wait')
            self.dialog.update()
            
            # 创建评价
            # 获取用户名，优先使用username，其次使用name，最后使用默认值
            user_name = getattr(self.user, 'username', None) or getattr(self.user, 'name', '匿名用户')
            
            review = self.review_service.add_review(
                user_id=self.user.user_id,
                product_id=self.product.product_id,
                order_id=self.order.order_id,
                rating=self.rating,
                comment=comment,
                user_name=user_name,
                images=self.saved_images  # 使用保存后的路径
            )
            
            # 恢复鼠标样式
            self.dialog.config(cursor='')
            
            if review:
                # 显示成功消息
                messagebox.showinfo('评价成功', '🎉 感谢您的评价！您的反馈对我们很重要。')
                
                # 通知主控制器刷新商品详情页面的评价列表
                if hasattr(self.controller, 'refresh_current_page_reviews'):
                    self.controller.refresh_current_page_reviews()
                
                self.dialog.destroy()
            else:
                messagebox.showerror('评价失败', '评价提交失败，请重试')
                
        except Exception as e:
            # 恢复鼠标样式
            self.dialog.config(cursor='')
            error(f"提交评价失败: {e}")
            messagebox.showerror('评价失败', f'提交时发生错误: {e}')
    
    def _cancel(self):
        """取消评价"""
        self.dialog.destroy()
